home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / text / hyper / ADtoHT2_1.lha / Source.lha / File.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-22  |  19.2 KB  |  783 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /* The file functions.                                                  */
  4. /* These functions handle one read-file and one write-file.             */
  5. /*                                                                      */
  6. /************************************************************************/
  7.  
  8. #include <proto/alib.h>
  9. #include <proto/exec.h>
  10. #include <proto/dos.h>
  11.  
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <ctype.h>
  16. #include <stdarg.h>
  17. #include <errno.h>
  18.  
  19. /************************************************************************/
  20.  
  21. #include "main.h"
  22. #include "File.h"
  23. #include "Version.h"
  24.  
  25. /************************************************************************/
  26.  
  27. char *ReadFilename, *WriteFilename;
  28.  
  29. static FILE *WriteHandle, *ReadHandle;
  30. static ULONG ReadLineNo;
  31. static int ReadColumn;
  32.  
  33. static struct MinList UnreadList;
  34.  
  35. /************************************************************************/
  36. /*                                                                      */
  37. /* Return complete filename                                             */
  38. /*                                                                      */
  39. /************************************************************************/
  40.  
  41. static char *
  42. GetFilename (int DirNumber, char *Name)
  43.  
  44. {
  45.   int FilenameLength;
  46.   char *Filename;
  47.   int FirstError;
  48.  
  49.   FirstError=TRUE;
  50.   FilenameLength = 256;
  51.   while (TRUE)
  52.     {
  53.       Filename = xmalloc (FilenameLength);
  54.     NoMemReTry:
  55.       if (NameFromLock (Dirs[CURRENTDIR], Filename, FilenameLength))
  56.     {
  57.       if (DirNumber == CURRENTDIR || AddPart (Filename, Arguments.Dirs[DirNumber], FilenameLength))
  58.         {
  59.           if (AddPart (Filename, Name, FilenameLength))
  60.         {
  61.           return Filename;
  62.         }
  63.         }
  64.     }
  65.       else
  66.     {
  67.       switch(IoErr())
  68.         {
  69.         case ERROR_NO_FREE_STORE:
  70.           {
  71.         if (FirstError)
  72.           {
  73.             errno=ENOMEM;
  74.             perror("Current directory");
  75.             FirstError=FALSE;
  76.           }
  77.         Delay(2*TICKS_PER_SECOND);
  78.         if (!CheckSignal(SIGBREAKF_CTRL_C))
  79.           {
  80.             goto NoMemReTry;
  81.           }
  82.         errno=ERROR_BREAK;
  83.         perror(NULL);
  84.         CloseAll(RETURN_ERROR);
  85.           }
  86.           break;
  87.  
  88.         case ERROR_LINE_TOO_LONG:
  89.           {
  90.         free (Filename);
  91.         FilenameLength += 256;
  92.           }
  93.           break;
  94.  
  95.         default:
  96.           {
  97.         errno=IoErr();
  98.         perror ("Current directory");
  99.         CloseAll (RETURN_ERROR);
  100.           }
  101.           break;
  102.  
  103.         }
  104.     }
  105.     }
  106.   /* not reached */
  107. }
  108.  
  109. /************************************************************************/
  110. /*                                                                      */
  111. /* Open a file for reading.                                             */
  112. /*                                                                      */
  113. /************************************************************************/
  114.  
  115. void
  116. ROpen (int DirNumber, char *Name)
  117.  
  118. {
  119.   int FirstError;
  120.  
  121.   ReadFilename = GetFilename (DirNumber, Name);
  122.  
  123.   NewList ((struct List *) &UnreadList);
  124.  
  125.   CurrentDir (Dirs[DirNumber]);
  126.   FirstError=TRUE;
  127.   while (!(ReadHandle = fopen (ReadFilename, "r")))
  128.     {
  129.       if (errno==ENOMEM)
  130.     {
  131.       if (FirstError)
  132.         {
  133.           perror(ReadFilename);
  134.           FirstError=FALSE;
  135.         }
  136.       Delay(2*TICKS_PER_SECOND);
  137.       if (CheckSignal(SIGBREAKF_CTRL_C))
  138.         {
  139.           errno=ERROR_BREAK;
  140.           perror(NULL);
  141.           CloseAll(RETURN_ERROR);
  142.         }
  143.     }
  144.       else
  145.     {
  146.       perror (ReadFilename);
  147.       CloseAll (RETURN_ERROR);
  148.     }
  149.     }
  150.   SetVBuf (fileno(ReadHandle), NULL, BUF_FULL, 16 * 1024);
  151.  
  152.   ReadLineNo = 1;
  153.   ReadColumn = 0;
  154. }
  155.  
  156. /************************************************************************/
  157. /*                                                                      */
  158. /* Create a directory tree                                              */
  159. /*                                                                      */
  160. /************************************************************************/
  161.  
  162. static void
  163. CreateDirectory (char *Name)
  164.  
  165. {
  166.   BPTR DirLock;
  167.  
  168.   if (!Name[0])
  169.     {
  170.       return;
  171.     }
  172.  
  173.   if ((DirLock = Lock (Name, SHARED_LOCK)))
  174.     {
  175.       UnLock (DirLock);
  176.       return;
  177.     }
  178.  
  179.   if (IoErr () == ERROR_OBJECT_NOT_FOUND)
  180.     {
  181.       char *t;
  182.  
  183.       t = PathPart (Name);
  184.       if (t != Name)
  185.     {
  186.       char c;
  187.  
  188.       c = *t;
  189.       *t = '\0';
  190.       CreateDirectory (Name);
  191.       *t = c;
  192.     }
  193.       if ((DirLock = CreateDir (Name)))
  194.     {
  195.       UnLock (DirLock);
  196.       return;
  197.     }
  198.     }
  199.   errno=IoErr();
  200.   perror (Name);
  201.   CloseAll (RETURN_ERROR);
  202. }
  203.  
  204. /************************************************************************/
  205. /*                                                                      */
  206. /* Open a file for writing.                                             */
  207. /*                                                                      */
  208. /************************************************************************/
  209.  
  210. void
  211. WOpen (int DirNumber, char *Name)
  212.  
  213. {
  214.   WriteFilename = GetFilename (DirNumber, Name);
  215.  
  216.   if (Pass2)
  217.     {
  218.       char *t;
  219.       char c;
  220.       int FirstError;
  221.  
  222.       CurrentDir (Dirs[DirNumber]);
  223.       t = PathPart (WriteFilename);
  224.       c = *t;
  225.       *t = '\0';
  226.       CreateDirectory (WriteFilename);
  227.       *t = c;
  228.       FirstError=TRUE;
  229.       while (!(WriteHandle = fopen (WriteFilename, "w")))
  230.     {
  231.       if (errno==ENOMEM)
  232.         {
  233.           if (FirstError)
  234.         {
  235.           perror(WriteFilename);
  236.           FirstError=FALSE;
  237.         }
  238.           Delay(2*TICKS_PER_SECOND);
  239.           if (CheckSignal(SIGBREAKF_CTRL_C))
  240.         {
  241.           errno=ERROR_BREAK;
  242.           perror(NULL);
  243.           SetRC(RETURN_ERROR);
  244.           break;
  245.         }
  246.         }
  247.       else
  248.         {
  249.           perror (WriteFilename);
  250.           SetRC (RETURN_ERROR);
  251.           break;
  252.         }
  253.     }
  254.       if (WriteHandle)
  255.     {
  256.       SetVBuf (fileno(WriteHandle), NULL, BUF_FULL, 16 * 1024);
  257.     }
  258.     }
  259. }
  260.  
  261. /************************************************************************/
  262. /*                                                                      */
  263. /* Close the read-file.                                                 */
  264. /*                                                                      */
  265. /************************************************************************/
  266.  
  267. void
  268. RClose (void)
  269.  
  270. {
  271.   if (ReadHandle)
  272.     {
  273.       fclose (ReadHandle);
  274.       ReadHandle = NULL;
  275.       free (ReadFilename);
  276.     }
  277.  
  278.   if (UnreadList.mlh_Head)
  279.     {
  280.       struct Word *Word;
  281.  
  282.       while ((Word = (struct Word *) RemTail ((struct List *) &UnreadList)))
  283.     {
  284.       FreeWord (Word);
  285.     }
  286.     }
  287. }
  288.  
  289. /************************************************************************/
  290. /*                                                                      */
  291. /* Close the write-file.                                                */
  292. /*                                                                      */
  293. /************************************************************************/
  294.  
  295. void
  296. WClose (void)
  297.  
  298. {
  299.   if (WriteHandle)
  300.     {
  301.       if (fclose (WriteHandle)==EOF)
  302.     {
  303.       perror (WriteFilename);
  304.       SetRC (RETURN_ERROR);
  305.     }
  306.       SetProtection (WriteFilename, FIBF_EXECUTE);
  307.       WriteHandle = NULL;
  308.     }
  309.   if (WriteFilename)
  310.     {
  311.       free(WriteFilename);
  312.       WriteFilename=NULL;
  313.     }
  314. }
  315.  
  316. /************************************************************************/
  317. /*                                                                      */
  318. /* Read a word from the read-file. This is just an internal function.    */
  319. /*                                                                      */
  320. /************************************************************************/
  321.  
  322. struct Word *BasicReadWord (int AllowEOF)
  323.  
  324. {
  325.   struct Word *NewWord;
  326.  
  327.   if (CheckSignal (SIGBREAKF_CTRL_C))
  328.     {
  329.       errno=ERROR_BREAK;
  330.       perror (NULL);
  331.       CloseAll (RETURN_WARN);
  332.     }
  333.  
  334.   if (!(NewWord = (struct Word *) RemTail ((struct List *) &UnreadList)))
  335.     {
  336.       struct Word Word;
  337.       int StartColumn;
  338.  
  339.       memset (&Word, 0, sizeof (Word));
  340.  
  341.       StartColumn = ReadColumn;
  342.  
  343.       NewWord = NULL;
  344.       while (!NewWord)
  345.     {
  346.       static char *InputBuffer;
  347.       static size_t InputBufferSize;
  348.  
  349.       int c;
  350.  
  351.       Word.Line = ReadLineNo;
  352.  
  353.       c = fgetc (ReadHandle);
  354.       ReadColumn++;
  355.       if (c == '\t')
  356.         {
  357.           /* really +8, but we have already added 1 */
  358.           ReadColumn = (ReadColumn + 7) & ~7;
  359.         }
  360.       else if (isalpha (c) || c == '_')
  361.         {
  362.           Word.Whitespace = ReadColumn - StartColumn - 1;
  363.           while (isalpha (c) || isdigit (c) || c == '_')
  364.         {
  365.           if ((isupper (c) && Word.Length > 0) ||
  366.               isdigit (c) ||
  367.               c == '_')
  368.             {
  369.               Word.Special = TRUE;
  370.             }
  371.           if (Word.Length+1>=InputBufferSize)
  372.             {
  373.               InputBuffer=xrealloc(InputBuffer,InputBufferSize+=128);
  374.             }
  375.           InputBuffer[Word.Length++] = c;
  376.           c = fgetc (ReadHandle);
  377.           ReadColumn++;
  378.         }
  379.           if (ferror (ReadHandle))
  380.         {
  381.           perror (ReadFilename);
  382.           CloseAll (RETURN_ERROR);
  383.         }
  384.           ungetc (c,ReadHandle);
  385.           ReadColumn--;
  386.  
  387.           InputBuffer[Word.Length] = '\0';
  388.           NewWord = xmalloc (sizeof (*NewWord) + Word.Length);
  389.           *NewWord = Word;
  390.           strcpy (NewWord->Word, InputBuffer);
  391.         }
  392.       else if (isdigit(c))
  393.         {
  394.           Word.Whitespace = ReadColumn - StartColumn - 1;
  395.           while (isdigit(c) || c=='x')
  396.         {
  397.           if (Word.Length+1>=InputBufferSize)
  398.             {
  399.               InputBuffer=xrealloc(InputBuffer,InputBufferSize+=128);
  400.             }
  401.           InputBuffer[Word.Length++]=c;
  402.           c=fgetc(ReadHandle);
  403.           ReadColumn++;
  404.         }
  405.           if (ferror(ReadHandle))
  406.         {
  407.           perror(ReadFilename);
  408.           CloseAll(RETURN_ERROR);
  409.         }
  410.           ungetc(c,ReadHandle);
  411.           ReadColumn--;
  412.  
  413.           InputBuffer[Word.Length] = '\0';
  414.           NewWord = xmalloc (sizeof (*NewWord) + Word.Length);
  415.           *NewWord = Word;
  416.           strcpy (NewWord->Word, InputBuffer);
  417.         }
  418.       else if (c == '\n')
  419.         {
  420.           Word.Newline++;
  421.           StartColumn = 0;
  422.           ReadColumn = 0;
  423.           ReadLineNo++;
  424.         }
  425.       else if (c == EOF)
  426.         {
  427.           if (ferror(ReadHandle))
  428.         {
  429.           perror (ReadFilename);
  430.           CloseAll (RETURN_ERROR);
  431.         }
  432.           if (!AllowEOF)
  433.         {
  434.           fprintf (stderr, "%s: unexpected end of file\n", ReadFilename);
  435.           CloseAll (RETURN_ERROR);
  436.         }
  437.           NewWord = xmalloc (sizeof (*NewWord));
  438.           *NewWord = Word;
  439.           NewWord->Word[0] = '\0';
  440.           NewWord->Whitespace = 0;
  441.           NewWord->Newline = (NewWord->Newline > 0);
  442.           NewWord->Special=TRUE;
  443.         }
  444.       else if (c != ' ')
  445.         {
  446.           if (c == 0x0c)
  447.         {
  448.           ReadColumn = 0;
  449.           Word.Whitespace = 0;
  450.         }
  451.           else
  452.         {
  453.           Word.Whitespace = ReadColumn - StartColumn - 1;
  454.         }
  455.           NewWord = xmalloc (sizeof (*NewWord) + 1);
  456.           *NewWord = Word;
  457.           NewWord->Word[0] = c;
  458.           NewWord->Word[1] = '\0';
  459.           NewWord->Length = 1;
  460.           NewWord->Special = TRUE;
  461.         }
  462.     }
  463.     }
  464.   return NewWord;
  465. }
  466.  
  467.  
  468. /************************************************************************/
  469. /*                                                                      */
  470. /* Concat several words to one.                        */
  471. /* Intervening whitespace and newlines are ignored.            */
  472. /* The individual words are freed.                    */
  473. /*                                                                      */
  474. /************************************************************************/
  475.  
  476. static struct Word *ConcatWords(struct Word *FirstWord, ...)
  477.  
  478. {
  479.   struct Word **CurrentWord;
  480.   struct Word *NewWord;
  481.   size_t NewLength;
  482.   char *t;
  483.  
  484.   NewLength=0;
  485.   for (CurrentWord=&FirstWord; *CurrentWord; CurrentWord++)
  486.     {
  487.       NewLength+=(*CurrentWord)->Length;
  488.     }
  489.  
  490.   NewWord=xmalloc(sizeof(*NewWord)+NewLength);
  491.   NewWord->Line=FirstWord->Line;
  492.   NewWord->Whitespace=FirstWord->Whitespace;
  493.   NewWord->Newline=FirstWord->Newline;
  494.   NewWord->Special=TRUE;
  495.   NewWord->Length=NewLength;
  496.  
  497.   t=NewWord->Word;
  498.   for (CurrentWord=&FirstWord; *CurrentWord; CurrentWord++)
  499.     {
  500.       t=stpcpy(t,(*CurrentWord)->Word);
  501.       FreeWord(*CurrentWord);
  502.     }
  503.  
  504.   return NewWord;
  505. }
  506.  
  507. /************************************************************************/
  508. /*                                                                      */
  509. /* Read a word. This is the real function that will handle all known    */
  510. /* exceptions to the normal word definition.                */
  511. /*                                                                      */
  512. /************************************************************************/
  513.  
  514. struct Word *ReadWord(int AllowEOF)
  515.  
  516. {
  517.   struct Word *Word;
  518.   struct Word *NextWord;
  519.  
  520.   Word=BasicReadWord(AllowEOF);
  521.   NextWord=BasicReadWord(TRUE);
  522.  
  523.   /* 8svx */
  524.   if (!strcmp(Word->Word,"8"))
  525.     {
  526.       if (!NextWord->Whitespace && !NextWord->Newline && !strcasecmp(NextWord->Word,"svx"))
  527.     {
  528.       Word=ConcatWords(Word,NextWord,NULL);
  529.       NextWord=BasicReadWord(TRUE);
  530.     }
  531.     }
  532.  
  533.   /* -handler */
  534.   if (!NextWord->Whitespace && !NextWord->Newline && !strcmp(NextWord->Word,"-"))
  535.     {
  536.       struct Word *NextNextWord;
  537.  
  538.       NextNextWord=BasicReadWord(TRUE);
  539.       if (!NextNextWord->Whitespace && !NextNextWord->Newline && !strcasecmp(NextNextWord->Word,"handler"))
  540.     {
  541.       Word=ConcatWords(Word,NextWord,NextNextWord,NULL);
  542.       NextWord=BasicReadWord(TRUE);
  543.     }
  544.       else
  545.     {
  546.       UnreadWord(NextNextWord);
  547.     }
  548.     }
  549.  
  550.   /* .irgendwas */
  551.   if (!NextWord->Whitespace && !NextWord->Newline && !strcmp(NextWord->Word,"."))
  552.     {
  553.       struct Word *NextNextWord;
  554.  
  555.       NextNextWord=BasicReadWord(TRUE);
  556.       if (!NextNextWord->Whitespace && !NextNextWord->Newline && !NextNextWord->Special)
  557.     {
  558.       Word=ConcatWords(Word,NextWord,NextNextWord,NULL);
  559.       NextWord=BasicReadWord(TRUE);
  560.     }
  561.       else
  562.     {
  563.       UnreadWord(NextNextWord);
  564.     }
  565.     }
  566.   UnreadWord(NextWord);
  567.   return Word;
  568. }
  569.  
  570. /************************************************************************/
  571. /*                                                                      */
  572. /* Unread a word back to the read-file                                  */
  573. /*                                                                      */
  574. /************************************************************************/
  575.  
  576. void UnreadWord (struct Word *Word)
  577.  
  578. {
  579.   AddTail ((struct List *) &UnreadList, (struct Node *) &Word->Node);
  580. }
  581.  
  582. /************************************************************************/
  583. /*                                                                      */
  584. /* Read until a terminating word                                        */
  585. /* The terminator is unread                                             */
  586. /*                                                                      */
  587. /************************************************************************/
  588.  
  589. char *
  590. ReadUntil (char *Terminator)
  591.  
  592. {
  593.   struct MinList WordList;
  594.   struct Word *Word;
  595.   size_t Length;
  596.   char *Text, *t;
  597.  
  598.   NewList ((struct List *) &WordList);
  599.   Length = 1;
  600.   Word = ReadWord (FALSE);
  601.   while (strcmp (Word->Word, Terminator))
  602.     {
  603.       AddTail ((struct List *) &WordList, (struct Node *) Word);
  604.       Length += Word->Length + Word->Whitespace;
  605.       Word = ReadWord (FALSE);
  606.     }
  607.   UnreadWord (Word);
  608.   t = Text = xmalloc (Length);
  609.   while ((Word = (struct Word *) RemHead ((struct List *) &WordList)))
  610.     {
  611.       while (Word->Whitespace)
  612.     {
  613.       *(t++) = ' ';
  614.       Word->Whitespace--;
  615.     }
  616.       t = stpcpy (t, Word->Word);
  617.       FreeWord (Word);
  618.     }
  619.   return Text;
  620. }
  621.  
  622. /************************************************************************/
  623. /*                                                                      */
  624. /* Write a formatted string to the write-file                           */
  625. /*                                                                      */
  626. /************************************************************************/
  627.  
  628. void
  629. WPrintf (char *FormatString,...)
  630.  
  631. {
  632.   if (WriteHandle)
  633.     {
  634.       va_list ParamList;
  635.  
  636.       va_start(ParamList,FormatString);
  637.       if (vfprintf (WriteHandle, FormatString, ParamList) == EOF)
  638.     {
  639.       va_end(ParamList);
  640.       perror (WriteFilename);
  641.       CloseAll (RETURN_ERROR);
  642.     }
  643.       va_end(ParamList);
  644.     }
  645. }
  646.  
  647. /************************************************************************/
  648. /*                                                                      */
  649. /* Write the header for an AmigaGuide file                              */
  650. /*                                                                      */
  651. /************************************************************************/
  652.  
  653. void
  654. WriteHeader (char *Database, char *Master)
  655.  
  656. {
  657.   if (Pass2)
  658.     {
  659.       struct DateTime DateTime;
  660.       char StrDate[LEN_DATSTRING], StrTime[LEN_DATSTRING];
  661.  
  662.       DateStamp (&DateTime.dat_Stamp);
  663.       DateTime.dat_Format = FORMAT_DOS;
  664.       DateTime.dat_Flags = 0;
  665.       DateTime.dat_StrDay = NULL;
  666.       DateTime.dat_StrDate = StrDate;
  667.       DateTime.dat_StrTime = StrTime;
  668.  
  669.       DateToStr (&DateTime);
  670.  
  671.       WPrintf ("@DATABASE \x22%s\x22\n", Database);
  672.       if (Master)
  673.     WPrintf ("@MASTER   \x22%s\x22\n", Master);
  674.       WPrintf ("@REMARK   This file was created by " PROGRAM_NAME " " PROGRAM_VERSION " on %s %s\n"
  675.            "@REMARK   Do not edit\n"
  676.            "@REMARK   ADtoHT is " PROGRAM_COPYRIGHT "\n",
  677.            StrDate, StrTime);
  678.     }
  679. }
  680.  
  681. /************************************************************************/
  682. /*                                                                      */
  683. /* Write a words white-space to the write-file                          */
  684. /*                                                                      */
  685. /************************************************************************/
  686.  
  687. void
  688. WriteWhitespace (struct Word *Word)
  689.  
  690. {
  691.   while (Word->Newline)
  692.     {
  693.       WPrintf ("\n");
  694.       Word->Newline--;
  695.     }
  696.   while (Word->Whitespace)
  697.     {
  698.       WPrintf (" ");
  699.       Word->Whitespace--;
  700.     }
  701. }
  702.  
  703. /************************************************************************/
  704. /*                                                                      */
  705. /* Write a word to the write-file                                       */
  706. /*                                                                      */
  707. /************************************************************************/
  708.  
  709. void
  710. WriteWord (struct Word *Word)
  711.  
  712. {
  713.   WriteWhitespace (Word);
  714.   if (Word->Length == 1)
  715.     {
  716.       switch (Word->Word[0])
  717.     {
  718.     case '\\':
  719.       WPrintf ("\\\\");
  720.       return;
  721.     case '@':
  722.       WPrintf ("@@");
  723.       return;
  724.     }
  725.     }
  726.   WPrintf ("%s", Word->Word);
  727. }
  728.  
  729. /************************************************************************/
  730. /*                                                                      */
  731. /* Skip Read-File until 0x0c is found                                    */
  732. /* Returns the last char read (may be -1 == EOF)                        */
  733. /*                                                                      */
  734. /************************************************************************/
  735.  
  736. long
  737. ReadSkip (void)
  738.  
  739. {
  740.   long c;
  741.   struct Word *Word;
  742.  
  743.   while ((Word=(struct Word *)RemTail((struct List *)&UnreadList)))
  744.     {
  745.       if (Word->Word[0]==0x0c)
  746.     {
  747.       return (long)Word->Word[0];
  748.     }
  749.       if (!Word->Word[0])
  750.     {
  751.       return -1;
  752.     }
  753.       FreeWord(Word);
  754.     }
  755.  
  756.   do
  757.     {
  758.       c = fgetc (ReadHandle);
  759.     }
  760.   while (c != 0x0c && c != EOF);
  761.  
  762.   return c;
  763. }
  764.  
  765. /************************************************************************/
  766. /*                                                                      */
  767. /* Output a bold, centered headline                                     */
  768. /*                                                                      */
  769. /************************************************************************/
  770.  
  771. void 
  772. WHeadline (char *Text)
  773.  
  774. {
  775.   int i;
  776.  
  777.   for (i = (*Arguments.Width - strlen (Text) - (*Arguments.Version >= 39)) / 2; i; i--)
  778.     {
  779.       WPrintf (" ");
  780.     }
  781.   WPrintf (*Arguments.Version >= 39 ? "@{b}%s@{ub}\n" : "%s\n", Text);
  782. }
  783.